<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>bitcoinjs.js</title>

        <script>

            //密码强度;
            function PasswordStrength(showed) {
                this.showed = (typeof (showed) == "boolean") ? showed : true;
                this.styles = new Array();
                this.styles[0] = {backgroundColor:"#EBEBEB", borderLeft:"solid 1px #FFFFFF", borderRight:"solid 1px #BEBEBE", borderBottom:"solid 1px #BEBEBE"};
                this.styles[1] = {backgroundColor:"#FF4545", borderLeft:"solid 1px #FFFFFF", borderRight:"solid 1px #BB2B2B", borderBottom:"solid 1px #BB2B2B"};
                this.styles[2] = {backgroundColor:"#FFD35E", borderLeft:"solid 1px #FFFFFF", borderRight:"solid 1px #E9AE10", borderBottom:"solid 1px #E9AE10"};
                this.styles[3] = {backgroundColor:"#95EB81", borderLeft:"solid 1px #FFFFFF", borderRight:"solid 1px #3BBC1B", borderBottom:"solid 1px #3BBC1B"};
                this.labels = ["\u5f31", "\u4e2d", "\u5f3a"];
                this.divName = "pwd_div_" + Math.ceil(Math.random() * 100000);
                this.minLen = 1;
                this.width = "150px";
                this.height = "16px";
                this.content = "";
                this.selectedIndex = 0;
                this.init();
            }
            PasswordStrength.prototype.init = function () {
                var s = "<table cellpadding=\"0\" id=\"" + this.divName + "_table\" cellspacing=\"0\" style=\"width:" + this.width + ";height:" + this.height + ";\">";
                s += "<tr>";
                for (var i = 0; i < 3; i++) {
                    s += "<td id=\"" + this.divName + "_td_" + i + "\" width=\"33%\" align=\"center\"><span style=\"font-size:1px\"> </span><span id=\"" + this.divName + "_label_" + i + "\" style=\"display:none;font-family: Courier New, Courier, mono;font-size: 12px;color: #000000;\">" + this.labels[i] + "</span></td>";
                }
                s += "</tr>";
                s += "</table>";
                this.content = s;
                if (this.showed) {
                    document.write(s);
                    this.copyToStyle(this.selectedIndex);
                }
            };
            PasswordStrength.prototype.copyToObject = function (o1, o2) {
                for (var i in o1) {
                    o2[i] = o1[i];
                }
            };
            PasswordStrength.prototype.copyToStyle = function (id) {
                this.selectedIndex = id;
                for (var i = 0; i < 3; i++) {
                    if (i == id - 1) {
                        this.$(this.divName + "_label_" + i).style.display = "inline";
                    } else {
                        this.$(this.divName + "_label_" + i).style.display = "none";
                    }
                }
                for (var i = 0; i < id; i++) {
                    this.copyToObject(this.styles[id], this.$(this.divName + "_td_" + i).style);
                }
                for (; i < 3; i++) {
                    this.copyToObject(this.styles[0], this.$(this.divName + "_td_" + i).style);
                }
            };
            PasswordStrength.prototype.$ = function (s) {
                return document.getElementById(s);
            };
            PasswordStrength.prototype.setSize = function (w, h) {
                this.width = w;
                this.height = h;
            };
            PasswordStrength.prototype.setMinLength = function (n) {
                if (isNaN(n)) {
                    return;
                }
                n = Number(n);
                if (n > 1) {
                    this.minLength = n;
                }
            };
            PasswordStrength.prototype.setStyles = function () {
                if (arguments.length == 0) {
                    return;
                }
                for (var i = 0; i < arguments.length && i < 4; i++) {
                    this.styles[i] = arguments[i];
                }
                this.copyToStyle(this.selectedIndex);
            };
            PasswordStrength.prototype.write = function (s) {
                if (this.showed) {
                    return;
                }
                var n = (s == "string") ? this.$(s) : s;
                if (typeof (n) != "object") {
                    return;
                }
                n.innerHTML = this.content;
                this.copyToStyle(this.selectedIndex);
            };
            PasswordStrength.prototype.update = function (s) {
                if (s.length < this.minLen) {
                    this.copyToStyle(0);
                    return;
                }
                var ls = -1;
                if (s.match(/[a-z]/ig)) {
                    ls++;
                }
                if (s.match(/[0-9]/ig)) {
                    ls++;
                }
                if (s.match(/(.[^a-z0-9])/ig)) {
                    ls++;
                }
                if (s.length < 6 && ls > 0) {
                    ls--;
                }
                switch (ls) {
                    case 0:
                        this.copyToStyle(1);
                        break;
                    case 1:
                        this.copyToStyle(2);
                        break;
                    case 2:
                        this.copyToStyle(3);
                        break;
                    default:
                        this.copyToStyle(0);
                }
            };


        </script>

        <script>

            function decrypt(){
                var k = $('#password').val();
                var encrypted = $('#encrypted').val();
                var s = Utils.AesDecrypt(encrypted, k);

                var result = s.toString(Bitcoin.CryptoJS.enc.Utf8);

                //实际上，明文有可能就是空字符串
                if(result == ""){
                    $('#decrypted').text("失败！").css({"color":"red"});
                } else {
                    $('#decrypted').text(result).css({"color":"black"});
                }
            }

            function encrypt(){
                var msg = $('#msg').val();
                var key = $('#key').val();
                var encryptedMsg = Utils.AesEncrypt(msg, key);
                $("#encryptedMsg").text(encryptedMsg.toString()).show()
            }

        </script>
	
	</head>	
<body>

<div>
    <div style="float: left;">
        <label>AES加密</label><br/><br/>
        <label>密码：</label><input id="key" value="1qazxsw2!@"/><br/><br/>
        <label>明文：</label><textarea id="msg" style="width:300px; height:50px;"></textarea><br/><br/>
        <input type="button" onclick="encrypt();" value="加密"><br/><br/>
        <label>密文：</label><span id="encryptedMsg"></span>
        <br/>
    </div>

    <div style="float: right;">
        <label>AES解密</label><br/><br/>
        <label>密码：</label><input id="password" value="1qazxsw2!@"/><br/><br/>
        <label>密文：</label><textarea id="encrypted" style="width:300px; height:50px;"></textarea><br/><br/>
        <input type="button" onclick="decrypt();" value="解密"><br/><br/>
        <label>明文：</label><span id="decrypted"></span>
        <br/>
    </div>

</div>



<br/><br/><br/><br/><br/><br/>


<div style="margin-top:200px; ">
    <h4>密码强度检测</h4>

    <table width="100%" border="0" cellspacing="1" cellpadding="0">
        <tr>
            <td width="100" align="right">强度显示：</td>
            <td>
                <script language="javascript">
                    var ps = new PasswordStrength();
                    ps.setSize("200","20");
                    ps.setMinLength(5);
                </script>
            </td>
        </tr>
        <tr>
            <td align="right">密码检测：</td>
            <td><input name="pwd" type="password" id="pwd" style="width:200px" onKeyUp="ps.update(this.value);"></td>
        </tr>
    </table>

    <label id="display"></label>
</div>

        <script src="Utils.js"></script>
	    <!--<script src="bitcoinjsok.min.js"></script>-->
        <script src="original/bitcoinjs.js"></script>
		<script src="jquery.min.js"></script>
        <script src="mnemonic.min.js"></script>

		<script type="text/javascript">


        var d = 0;
        var chainCode = new Bitcoin.Buffer(32);
        chainCode.fill(2)
        var hd = new Bitcoin.HDNode(d, chainCode);
        console.log(hd)










// ----AES 加解密

            var data = "mkzwG4Sreaw3tqte1StBD4Lsk1yRig2tYC";
            var key  = Bitcoin.CryptoJS.enc.Latin1.parse('bfe88e420d1b0a16489d83d961c68a7b');
            var iv   = Bitcoin.CryptoJS.enc.Latin1.parse('1234567812345678');

            //加密
            var encrypted = Bitcoin.CryptoJS.AES.encrypt(data,key,{iv:iv,mode:Bitcoin.CryptoJS.mode.CBC,padding:Bitcoin.CryptoJS.pad.Pkcs7});

            document.write(encrypted.ciphertext);
            document.write('<br/>');
            document.write(encrypted.key);
            document.write('<br/>');
            document.write(encrypted.iv);
            document.write('<br/>');
            document.write(encrypted.salt);
            document.write('<br/>');
            document.write(encrypted);
            document.write('<br/>');


            var encryptedStr = "kFOZIjLcUWffJZSHCCQF/svJga9+CxV6c+LpUQkB6eS2wdPGRnjauNKFGs07fHGH"
            //解密
            var decrypted = Bitcoin.CryptoJS.AES.decrypt(encryptedStr,key,{iv:iv,padding:Bitcoin.CryptoJS.pad.ZeroPadding});
            console.log(decrypted.toString(Bitcoin.CryptoJS.enc.Utf8));




















            var remark = $.trim("6f6b316c2ce682a8e5a5bde5958a");
            var txBuilder = new Bitcoin.TransactionBuilder();
            if(remark != ""){
                //txBuilder.addOutput(Utils.createOP_ReturnScript(remark), 0);
            }
            //var op_returnSc
            var remark = "d";
            //remark = ""
            var opReturn = Utils.createOP_ReturnScript(remark);

            console.log(opReturn.buffer.length);

            //return ;

            txBuilder.addOutput(Utils.createOP_ReturnScript("Hello, test leaveing messages on block ."), 0);
            txBuilder.addOutput(Utils.createOP_ReturnScript("0123456789-0123456789-0123456789"), 0);
            txBuilder.addOutput(Utils.createOP_ReturnScript("more than forty bytes?"), 0);
            txBuilder.addOutput(Utils.createOP_ReturnScript("-- okTest"), 0);


            var pw = "000000fang!";
            //pw = "U2FsdGVkX18RapJ7KqxTDb2tzE+wZDwWIscyw0NNRIw=";
            console.log("原文 " + pw);

            /*var arrayByte1 = stringToBytes(pw);
            console.log("原文直转数组 " + arrayByte1);*/

            //var array = wordsToBytes([pw]);

            var OKkey = "okcoinwallet";
            pw = Utils.AesEncrypt(pw, OKkey);
            console.log("AES " + pw);

            var arrayByte = Utils.stringToBytes(pw.toString());
            console.log("字节数组 " + arrayByte);

            var code = mnemonic.encode(arrayByte);
            console.log("密文 " + code);

            code = 'stuart-alabama-trapeze--image-design-spiral--vista-teacher-status--mayday-abraham-modular--strong-concept-solid--epoxy-cafe-multi--balance-mirror-sheriff--bronze-command-patriot--version-asia-tango--super-canvas-tennis--proton-ferrari-left';

            code = 'stuart-alabama-trapeze--image-design-spiral--iron-jaguar-vision--danube-balsa-rebel--light-open-market--mystery-omega-peru--mixer-plato-tripod--ivory-brandy-manager--genesis-golf-volcano--good-karl-patriot--formal-happy-left'

            code = "stuart-alabama-trapeze--image-design-spiral--celtic-ingrid-pacific--llama-exit-phone--ralph-magnum-news--tennis-everest-nepal--sabrina-pigment-stereo--union-avatar-market--camera-justin-relax--phrase-flex-horizon--horse-ohio-lecture"

            var decode = mnemonic.decode(code);
            console.log("解密 " + decode);
            var original = Utils.bytesToString(decode);
            console.log("还原 " + original);

            pw = Utils.AesDecrypt(original, OKkey);
            console.log("结果 " + pw.toString(Bitcoin.CryptoJS.enc.Utf8));



            console.log("************************************************");
            console.log("************************************************");
            console.log("************************************************");


            //var test = Bitcoin.CryptoJS.RIPEMD160
            //console.log(array);


			key1 = Bitcoin.ECKey.makeRandom();

           // var address = Bitcoin.Address.

			// Print your private key (in WIF format)
			console.log("Private key: " + key1.toWIF())
			// => Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct

            console.log("Public key: " + key1.pub.toHex());
	
			// Print your public key (toString defaults to a Bitcoin address)
			console.log("bitcoin Address: " + key1.pub.getAddress().toString())

            console.log("toOutputScript: " + key1.pub.getAddress().toOutputScript().toString())

            var liteAddr = key1.pub.getAddress(Utils.Litecoin);
            console.log("Litecoin Address: " + liteAddr.toString())

            console.log("testnet Address: " + key1.pub.getAddress(Utils.testnet).toString())
			
			$('#display').text( key1.pub.getAddress().toString() );


            console.log('##############################################');
			
			var hash = Bitcoin.crypto.sha256("qings2329", { asBytes: true });
            var encryptedx =  mnemonic.encode(hash)
            //console.log(encryptedx);
           // var x = Bitcoin.crypto.HmacSHA256();

            //var CryptoJS = require('crypto-js');
            var kk = "000000fang!";
            //kk="1qazxsw2!@"
            //kk="123456"
            var k = kk;
            //var k = Bitcoin.CryptoJS.enc.Utf8.parse(kk);
            var fakek = '123';

            var cfg = {};
            var iv = Bitcoin.CryptoJS.enc.Utf8.parse('1234567812345678');
            cfg["iv"] = iv;
            //cfg["mode"] = Bitcoin.CryptoJS.mode.CBC;
            cfg["padding"] = Bitcoin.CryptoJS.pad.ZeroPadding;


            //var y = AESEncrypt("fsfassdfa1dsfsf", k);
            var y = Utils.AesEncrypt("fsfassdfa1dsfsf", k);
           // var z = CryptoJS.AES.encrypt();
            //BitcoinCryptoJS.MD5
			console.log( '加密: ' + y.toString());

            y="U2FsdGVkX1938TvDj59GyoMTt6uG9hmhSu05fCsb&#47;&#47;p0&#47;s+tmRjGLndI8HTaH49v8eyj+LeGfro2l61XIJ2I2zpzi&#47;lRTbElCBQFEGOgXVs=";

            y ="U2FsdGVkX1938TvDj59GyoMTt6uG9hmhSu05fCsb//p0/s+tmRjGLndI8HTaH49v8eyj+LeGfro2l61XIJ2I2zpzi/lRTbElCBQFEGOgXVs="




            //y="U2FsdGVkX18K4LRqVgUEq2SJFBMCwPfBcr9IW+OalDOMd0eIdSUE3tTGLlc9h8uqcXSwMBwbKIFHeEIRlUNvBlhkerdro74Km9OlXFOFO40=";

            //y="8c43f629f513da83109cd814f22e331afb0325979e1490e1e918291bf07961d737fe58572958d105574ad8746eea1c254e81da668ff60c3755e7f696cc82c54e"

           // y="U2FsdGVkX18IDly9EfHPDIEyoJ/XF8zZisVByyw+aakn1wHJxe5WzAb77FyimcPfFITAVKPpI1V3eWB45+E7pUWTUvwIk94hjH5lxqWnrTw="
            var s = Utils.AesDecrypt(y, k);
            console.log('decrypt: ' + s.words);

            var result = s.toString(Bitcoin.CryptoJS.enc.Utf8);

            console.log('解密: ' + result);

            var str = "U2FsdGVkX18+0ibiPPSLsRiMdYADEMT9NTek1bRJl0Gqx3M6YxCjJjYag4SbVUlZMd7gtWS4FxdRqulFTxrt5hGUHboMV/tFhZRKGnR3Z8U=";
            console.log('编码: ' + encodeURIComponent(str));



            var tx = new Bitcoin.Transaction();

            tx.addInput("aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31", 0)
            tx.addOutput("1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK", 15000)

            key = Bitcoin.ECKey.fromWIF("L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy")

            tx.sign(0, key)

            console.log(tx.toHex())

            console.log("**************yyyyyyyyyyyy*********************");

            var txBuilder = new Bitcoin.TransactionBuilder();
            txBuilder.toString();

            console.log("**************test address*********************");

            var addrStr = "7SeEnXWPaCCALbVrTnszCVGfRU8cGfx";//无效；

            addrStr = "1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH";//有效

            addrStr = "mrUmZv83b57BLeAfjESKKrvfQkVA2xm1yo";//有效

            try{
                addr = Bitcoin.Address.fromBase58Check(addrStr)
                console.log( addrStr + " 是有效地址" )
            }catch (e){
                console.log( addrStr + " 不是有效地址，异常信息：" + e.toString() )
            }


            console.log("################ 构建交易单 ##################")

            var txb = new Bitcoin.TransactionBuilder()

            var prevTx = new Bitcoin.Transaction()
             prevTx.addOutput('1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH', 0)
             prevTx.addOutput('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', 1)

            var prevTxHash = prevTx.getHash()
            console.log("prevTxHash:")
            console.log(prevTxHash.toString("hex"))

            var prevTxId = prevTx.getId()
            console.log("prevTxId:")
            console.log(prevTxId)

            console.log("****** hex:")
            console.log(prevTx.toHex())

            /*var vin = txb.addInput(prevTxHash, 1, 54)
            console.log(vin)*/

            var txid1 = "ea81e7d6b42bab0344af173f18a7196a0b95d4b07bee2c1f3708f41c48a5b94b";
            txb.addInput(txid1, 0)
            var targetAddr = "n1o8upU5tVSEVVXpD2b2yVtVdGHsCWDFvB"
            txb.addOutput(targetAddr, 15000)

            var priKey = "L4p6fXctmzzggK5nzjAN1scQCTXKQa2Qenfu85kbvLvwobjrpNaR"
            priKey = Bitcoin.ECKey.fromWIF(priKey);

            txb.sign(0, priKey);
            var x = txb.build();
            console.log("构建交易单的hex")
            console.log(x.toHex())

            console.log("----------------- txid: \n" + x.getId())



            //txb.signatures[i].signatures[0].toDER().toString("hex");
            //console.log("—————————toScriptSignature—————————————————")
            //console.log(txb.signatures[0].signatures[0].toScriptSignature());

            console.log("—————————toDER—————————————————")
            console.log(txb.signatures[0].signatures[0].toDER().toString("hex"));

            //md5
            var md5 = Bitcoin.CryptoJS.MD5("testfdsafsdfadafsdfasdadfasfasf");
            console.log("**********************:\n" +  md5 +" \n******************************\n")





            var bitcoin = Bitcoin;

            var privKeys = [bitcoin.ECKey.makeRandom(), bitcoin.ECKey.makeRandom(), bitcoin.ECKey.makeRandom()]
            var pubKeys = privKeys.map(function(x) { return x.pub })

            var redeemScript = bitcoin.scripts.multisigOutput(2, pubKeys) // 2 of 3
            var scriptPubKey = bitcoin.scripts.scriptHashOutput(redeemScript.getHash())

            var multisigAddress = bitcoin.Address.fromOutputScript(scriptPubKey).toString()

            console.log("multisigP2SH:", multisigAddress)



           var testnet = bitcoin.networks.testnet


           var data = new Buffer('cafedeadbeef', 'hex')
           var dataScript = bitcoin.scripts.nullDataOutput(data)



//////////////////////////////////////////////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////



            var bytesToHex = Bitcoin.convert.bytesToHex;
            var hexToBytes = Bitcoin.convert.hexToBytes;

            var rootUrl = "https://api.blockcypher.com/v1/btc/test3";
            // please do not drain our test account, if you need testnet BTC use a faucet
            // https://tpfaucet.appspot.com/
            var source = {
                private : "1af97b1f428ac89b7d35323ea7a68aba8cad178a04eddbbf591f65671bae48a2",
                public  : "03bb318b00de944086fad67ab78a832eb1bf26916053ecd3b14a3f48f9fbe0821f",
                address : "mtWg6ccLiZWw2Et7E5UqmHsYgrAi5wqiov"
            }
            var key   = Bitcoin.ECKey.fromHex(source.private);

            var addrs = [];

            // 0. We get 3 newly generated address
            function logAddrs(dest1, dest2, dest3) {
                addrs[0] = dest1[0];
                addrs[1] = dest2[0];
                addrs[2] = dest3[0];
                log("Generated 3 new addresses for 2-of-3 multisig.");
            }

            // 1. Post our funding transaction, sending money from a standard address to the multisig
            // address for our 3 keys.
            function newFundingTransaction() {
                var newtx = {
                    "inputs": [{"addresses": [source.address]}],
                    "outputs": [{
                        "addresses"   : [addrs[0].public, addrs[1].public, addrs[2].public],
                        "script_type" : "multisig-2-of-3",
                        "value"       : 25000,
                    }]
                }
                return $.post(rootUrl+"/txs/new", JSON.stringify(newtx));
            }

            // 2. Sign the hexadecimal strings returned with the fully built transaction and include
            //    the source public address.
            function signAndSend(newtx) {
                if (checkError(newtx)) return;

                newtx.pubkeys     = [];
                newtx.signatures  = newtx.tosign.map(function(tosign) {
                    newtx.pubkeys.push(source.public);
                    return bytesToHex(key.sign(hexToBytes(tosign)));
                });
                return $.post(rootUrl+"/txs/send", JSON.stringify(newtx));
            }

            // 3. Open a websocket to wait for confirmation the transaction has been accepted in a block.
            function waitForConfirmation(finaltx) {
                if (checkError(finaltx)) return;
                console.log(finaltx);
                log("Transaction " + finaltx.tx.hash + " to address " + finaltx.tx.outputs[0].addresses[0] + " of " +
                        finaltx.tx.outputs[0].value/100000000 + " BTC sent.");

                var confirmed = $.Deferred();
                var ws = new WebSocket("ws://socket.blockcypher.com/v1/btc/test3");
                // We keep pinging on a timer to keep the websocket alive
                var ping = pinger(ws);

                ws.onmessage = function (event) {
                    if (JSON.parse(event.data).confirmations > 0) {
                        log("Transaction confirmed.");
                        confirmed.resolve();
                        ping.stop();
                        ws.close();
                    }
                }
                ws.onopen = function(event) {
                    ws.send(JSON.stringify({filter: "event=new-block-tx&hash="+finaltx.tx.hash}));
                }
                log("Waiting for confirmation... (may take > 10 min)");
                return confirmed;
            }

            function newTwoOfThreeTransaction() {
                var newtx = {
                    "inputs": [{
                        "addresses"   : [addrs[0].public, addrs[1].public, addrs[2].public],
                        "script_type" : "multisig-2-of-3"
                    }],
                    "outputs": [{
                        "addresses" : [source.address],
                        "value"     : 15000
                    }]
                }
                return $.post(rootUrl+"/txs/new", JSON.stringify(newtx));
            }

            function signForAddressAndSend(addressNum) {
                return function(newtx) {
                    if (checkError(newtx)) return;
                    console.log(addrs[addressNum-1]);

                    var key = Bitcoin.ECKey.fromHex(addrs[addressNum-1].private);
                    newtx.signatures  = newtx.tosign.map(function(tosign) {
                        return bytesToHex(key.sign(hexToBytes(tosign)));
                    });
                    return $.post(rootUrl+"/txs/send", JSON.stringify(newtx));
                }
            }

            function pinger(ws) {
                var timer = setInterval(function() {
                    if (ws.readyState == 1) {
                        ws.send(JSON.stringify({event: "ping"}));
                    }
                }, 5000);
                return {stop: function() { clearInterval(timer); }};
            }

            function checkError(msg) {
                if (msg.errors && msg.errors.length) {
                    log("Errors occured!!/n" + msg.errors.join("/n"));
                    return true;
                }
            }

            function log(msg) {
                $("div.log").append("<div>" + msg + "</div>")
            }

            // Chaining
            $.when($.post(rootUrl+"/addrs?a"), $.post(rootUrl+"/addrs?b"), $.post(rootUrl+"/addrs?c"))
                    .then(logAddrs)
                // funding transaction to multisig address
                    .then(newFundingTransaction)
                    .then(signAndSend)
                    .then(waitForConfirmation)
                // transfer signing with key #3
                    .then(newTwoOfThreeTransaction)
                    .then(signForAddressAndSend(3))
                // transfer signing with key #1
                    .then(newTwoOfThreeTransaction)
                    .then(signForAddressAndSend(1))
                // final confirmation
                    .then(waitForConfirmation);
		</script>

		
</body>
</html>